package com.like.bluetooth.sample.classic

import android.annotation.SuppressLint
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableInt
import androidx.lifecycle.lifecycleScope
import com.like.bluetooth.classic.client.scan.executor.AbstractScanExecutor
import com.like.bluetooth.classic.client.scan.executor.ScanExecutorFactory
import com.like.bluetooth.exception.BluetoothException
import com.like.bluetooth.exception.BluetoothExceptionBusy
import com.like.bluetooth.exception.BluetoothExceptionCancelTimeout
import com.like.bluetooth.exception.BluetoothExceptionTimeout
import com.like.bluetooth.sample.R
import com.like.bluetooth.sample.databinding.ActivityClassicScanBinding
import com.like.bluetooth.util.BluetoothPermissionUtils
import com.like.common.util.Logger
import com.like.common.util.startActivity
import com.like.recyclerview.layoutmanager.WrapLinearLayoutManager
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.launch

/**
 * 扫描设备界面
 */
class ClassicScanActivity : AppCompatActivity() {
    private val mBinding: ActivityClassicScanBinding by lazy {
        DataBindingUtil.setContentView(this, R.layout.activity_classic_scan)
    }
    private val mAdapter: ClassicScanAdapter by lazy {
        ClassicScanAdapter {
            stopScan()
            startActivity<ClassicConnectActivity>(ClassicConnectActivity.KEY_DATA to it)
        }
    }
    private val scanExecutor: AbstractScanExecutor by lazy {
        ScanExecutorFactory.get(this).apply {
            onBleOn = {
                if (mBinding.tvScanStatus.text != "扫描未启动") {
                    val blueColor = ContextCompat.getColor(this@ClassicScanActivity, R.color.ble_text_blue)
                    mBinding.tvScanStatus.setTextColor(blueColor)
                    mBinding.tvScanStatus.text = "蓝牙已打开"
                }
            }
            onBleOff = {
                val redColor = ContextCompat.getColor(this@ClassicScanActivity, R.color.ble_text_red)
                mBinding.tvScanStatus.setTextColor(redColor)
                mBinding.tvScanStatus.text = "蓝牙未打开"
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding.rv.layoutManager = WrapLinearLayoutManager(this)
        mBinding.rv.adapter = mAdapter
        mBinding.btnStartScan.setOnClickListener {
            startScan()
        }
        mBinding.btnStopScan.setOnClickListener {
            stopScan()
        }
    }

    @SuppressLint("MissingPermission")
    private fun startScan() {
        lifecycleScope.launch {
            BluetoothPermissionUtils.requestScanEnvironment(this@ClassicScanActivity)
            var isFirstData = true
            mBinding.tvScanStatus.setTextColor(ContextCompat.getColor(this@ClassicScanActivity, R.color.ble_text_blue))
            mBinding.tvScanStatus.text = "扫描中……"
            scanExecutor.startScan()
                .catch {
                    Logger.e("ClassicScanActivity", "scan error $it")
                    when (it) {
                        is BluetoothExceptionCancelTimeout -> {
                            // 提前取消超时不做处理。因为这是调用 stopScan() 造成的，使用者可以直接在 stopScan() 方法结束后处理 UI 的显示，不需要此回调。
                        }

                        is BluetoothExceptionBusy -> {
                            mBinding.tvScanStatus.setTextColor(ContextCompat.getColor(this@ClassicScanActivity, R.color.ble_text_blue))
                            mBinding.tvScanStatus.text = "扫描中……"
                            Toast.makeText(this@ClassicScanActivity, it.message, Toast.LENGTH_SHORT).show()
                        }

                        is BluetoothExceptionTimeout -> {
                            mBinding.tvScanStatus.setTextColor(ContextCompat.getColor(this@ClassicScanActivity, R.color.ble_text_blue))
                            mBinding.tvScanStatus.text = "扫描完成"
                        }

                        else -> {
                            mBinding.tvScanStatus.setTextColor(ContextCompat.getColor(this@ClassicScanActivity, R.color.ble_text_red))
                            mBinding.tvScanStatus.text = it.message
                            mAdapter.submitList(null)
                        }
                    }
                }
                .conflate()// 如果消费者还在处理，则丢弃新的数据。然后消费者处理完后，再去获取生产者中的最新数据来处理。
                .collect {
                    if (isFirstData) {
                        isFirstData = false
                        mAdapter.submitList(null)
                    }
                    val name = it.device.name ?: "N/A"
                    val address = it.device.address ?: ""
                    Logger.w("ClassicScanActivity", "scan result $name $address")
                    val item: ClassicScanInfo? = mAdapter.currentList.firstOrNull { it?.address == address }
                    if (item == null) {// 防止重复添加
                        val newItems = mAdapter.currentList.toMutableList()
                        newItems.add(ClassicScanInfo(name, address, ObservableInt(it.rssi)))
                        mAdapter.submitList(newItems)
                    } else {
                        item.updateRssi(it.rssi)
                    }
                }
        }
    }

    private fun stopScan() {
        try {
            scanExecutor.stopScan()
            mBinding.tvScanStatus.setTextColor(ContextCompat.getColor(this, R.color.ble_text_blue))
            mBinding.tvScanStatus.text = "扫描停止了"
        } catch (e: BluetoothException) {
            mBinding.tvScanStatus.setTextColor(ContextCompat.getColor(this, R.color.ble_text_red))
            mBinding.tvScanStatus.text = e.message
        }
    }

    override fun onDestroy() {
        scanExecutor.close()
        super.onDestroy()
    }

}
